﻿
using System.Diagnostics.Metrics;
using System.Diagnostics.Tracing;

namespace CounterApp
{
    class Program
    {
        static long[] _counters = new long[60];
        static void Main(string[] args)
        {
            StartListener();
            var meter = new Meter("meter", "1.0.0");
            var counter = meter.CreateCounter<long>("counter");

            var timer = new System.Timers.Timer()
            {
                AutoReset = true,
                Enabled = true,
                Interval = 1 * 1000
            };

            timer.Elapsed += Timer_Elapsed;

            RunCounter(counter);
            while (!Console.KeyAvailable)
            {
                Thread.Sleep(1000);
            }

        }

        private static void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
        {
            _counters[DateTime.Now.AddSeconds(-2).Second] = 0;
            Console.WriteLine($"{DateTime.Now} : {_counters[DateTime.Now.AddMilliseconds(-1000).Second]}");
        }

        static void RunCounter(Counter<long> counter)
        {

            //for (int i = 0; i < 3; i++)
            //{
            _ = Task.Run(async () =>
            {
                do
                {
                    counter.Add(1);
                    await Task.Delay(10);
                } while (true);
            });
            //}
        }

        static void StartListener()
        {
            var listener = new MeterListener();

            // 创建的指标信息
            listener.InstrumentPublished = (instrument, meterListener) =>
            {
                Console.WriteLine($"EnableMeasurementEvents {instrument.Name} ");
                meterListener.EnableMeasurementEvents(instrument);
            };

            // 完成后的指标信息
            listener.MeasurementsCompleted = (instrument, state) =>
            {
                listener.DisableMeasurementEvents(instrument);
            };

            //测量值更新回调 注意类型
            listener.SetMeasurementEventCallback<long>((instrument, measurement, tags, state) =>
            {
                _counters[DateTime.Now.Second] += measurement;
                //Interlocked.Add(ref _counters[DateTime.Now.Second], measurement);

                //DateTime.Now.Ticks/ TimeSpan.TicksPerSecond

                //Console.WriteLine($"Instrument: {instrument.Name} has recorded the measurement {measurement}");
            });

            // 正在侦听的所有可观察仪器
            //listener.RecordObservableInstruments();

            // 开始侦听
            listener.Start();
        }
    }


    public class SimpleEventListener : EventListener
    {
        public SimpleEventListener()
        {
        }

        protected override void OnEventSourceCreated(EventSource source)
        {
            if (!source.Name.Equals("System.Runtime"))
            {
                return;
            }

            EnableEvents(source, EventLevel.Verbose, EventKeywords.All, new Dictionary<string, string?>()
            {
                ["EventCounterIntervalSec"] = "1"
            });
        }

        protected override void OnEventWritten(EventWrittenEventArgs eventData)
        {
            if (!eventData.EventName.Equals("EventCounters"))
            {
                return;
            }

            for (int i = 0; i < eventData.Payload.Count; ++i)
            {
                if (eventData.Payload[i] is IDictionary<string, object> eventPayload)
                {
                    var (counterName, counterValue) = GetRelevantMetric(eventPayload);
                    Console.WriteLine($"{counterName} : {counterValue}");
                }
            }
        }

        private static (string? counterName, string? counterValue) GetRelevantMetric(
            IDictionary<string, object> eventPayload)
        {
            var counterName = "";
            var counterValue = "";

            if (eventPayload.TryGetValue("DisplayName", out object? displayValue))
            {
                counterName = displayValue.ToString();
            }
            if (eventPayload.TryGetValue("Mean", out object? value) ||
                eventPayload.TryGetValue("Increment", out value))
            {
                counterValue = value.ToString();
            }

            return (counterName, counterValue);
        }
    }
}